home *** CD-ROM | disk | FTP | other *** search
- # include <stdio.h>
- # include <ingres.h>
- # include <aux.h>
- # include <catalog.h>
- # include <access.h>
- # include <batch.h>
- # include <opsys.h>
- # include <lock.h>
- # include <symbol.h>
- # include <resp.h>
- # include <dirent.h>
- # include <stdlib.h>
- # include <signal.h>
- # include <setjmp.h>
-
- /*
- ** INGRES crash recovery processor
- ** to recover a database you must be the dba or the ingres superuser
- ** RESTORE attempts to complete updates from batch files left in a
- ** database. After finishing all the batch files it calls PURGE.
- */
-
- # ifndef PURGE
- # define PURGE "purge"
- # endif PURGE
-
- /* first file to close on error */
- # define CLOSEFILES 3
-
- extern int Status;
- extern char *Usercode;
- char Utemp[2];
- char *Fileset;
- char Berror; /* batch error */
- char Error;
- extern char Ask;
- extern char Superuser;
- extern char All;
- extern char Qrymod;
- int Direc = CLOSEFILES - 1;
- extern int Wait_action;
- short tTvect[100];
- short tTdbu[100];
- struct resp Resp;
- DESC Btreesec;
- int Btree_fd;
- jmp_buf Jmpbuffer; /* buffer for nonlocal goto's on an error condition */
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- register int fd;
- register int i;
- register char *dbname;
- extern char *Proc_name;
- auto int stat;
- extern void (*ExitFn)();
- extern void rubproc();
- char *nargv[20];
- char **avp;
- char **fvp;
- extern char *Flagvect[];
- extern char *getnxtdb();
- char *lookucode();
-
- Proc_name = "RESTORE";
-
- /* check param list */
- argv[argc] = NULL;
- # ifdef xTTR1
- tTrace(argv, 'T', tTvect, 100);
- tTrace(argv, 'Z', tTdbu, 100);
- # endif
-
- initialize(argc, argv);
-
- /* do it to it */
- ExitFn = rubproc;
- signal(SIGQUIT, exit);
- while (dbname = getnxtdb())
- {
- Berror = Error = 0;
-
- /* first restart point for this database */
- setjmp(Jmpbuffer);
- if (Error) /* if set, will cause skip to next database */
- continue;
- printf("\nRestoring database: %s\t", dbname);
-
- acc_init();
- printf("owner: %s\n", lookucode(Admin.adhdr.adowner));
-
- /* set exclusive lock on data base */
- db_lock(M_EXCL);
-
- restore(); /* recover batch update and modify files */
- printf("\tRecovery of batch files complete.\n");
-
- /*
- ** second restart point for this database
- ** the batch files are completed and now the system
- ** relations need checking
- */
- setjmp(Jmpbuffer);
- if (Error) /* again, may cause skipping to next database */
- continue;
- printf("\tChecking system relations\n");
-
-
- /*
- ** check the relation relation
- ** this will mean checking for file existence,
- ** and whether the relstat bits are supported by
- ** the information in the other catalogs.
- */
- checkrel();
-
- /*
- ** check the attribute relation
- ** for each tuple in the attribute relation, there must
- ** be a tuple in the relation relation.
- ** the indexes relation doesn't need to be reverse checked
- ** into the relation relation since the order things are
- ** handled else where in the system is in the correct
- ** order. All the other catalogs need to be reverse checked.
- */
- checkatts();
-
- /* only check the qrymod catalogs if qrymod is turned on */
- if (Qrymod)
- {
- /* check the protect relation */
- checkprotect();
-
- /* check the integrities relation */
- checkinteg();
-
- /*
- ** check the tree relation
- ** must be done last since it depends upon
- ** a state of the system relations provided
- ** by the other check... routines.
- */
- checktree();
- }
-
- /* finished, close up the database and go on to the next */
- closecatalog(TRUE);
- unldb();
- acc_close();
-
- /* call PURGE if no errors */
- if (!Berror && !Error)
- {
- printf("\tCalling purge: ");
- fflush(stdout);
- if ((i = fork()) == -1)
- printf("Can't fork\n");
- else if (!i)
- {
- avp = nargv;
- *avp++ = "Purge";
- for (fvp = Flagvect; *fvp != NULL; )
- *avp++ = *fvp++;
- *avp++ = dbname;
- *avp++ = 0;
- # ifdef xTTR2
- if (tTf(0, 1))
- for (avp = nargv, i = 0; *avp != NULL; avp++, i++)
- printf("%d %s\n", i, *avp);
- # endif
- for (i=3; i <= NOFILE; i++)
- close(i);
- execv(ztack(Pathname, "/bin/purge"), nargv);
- execvp(PURGE, nargv);
- printf("Cannot exec %s\n", PURGE);
- exit(-1);
- }
- else
- wait(&stat);
- }
- }
- }
- /*
- ** RESTORE -- find the batch files and process them
- */
- restore()
- {
- DESC descr;
- register DIR *dirp;
- register struct dirent *dp;
- register int i;
- extern char *Fileset;
- extern void uperr(), (*ExitFn)();
- void (*tmpfn)();
- char *lookucode();
- char *fname;
-
- if ( (dirp = opendir(".")) == NULL )
- syserr("Can't open data base directory");
- bmove(Usercode, Utemp, UCODE_SZ);
- Batch_recovery = 1;
- tmpfn = ExitFn;
- ExitFn = uperr;
-
- /* restart point */
- setjmp(Jmpbuffer);
- for ( dp = readdir(dirp) ; dp != NULL ; dp = readdir(dirp) )
- {
- fname = dp->d_name;
- if ( !strcmp(".",fname) || !strcmp("..",fname) )
- continue;
- if (bequal("_SYSbatch", fname, 9))
- {
- Fileset = &fname[9];
- Batch_fp = open(batchname(), O_RDONLY);
- Batch_cnt = BATCHSIZE;
- getbatch(&Batchhd, sizeof(Batchhd));
- printf("\tFound batch file: %s\n", fname);
- printf("\tRelation: %s\tUser: %s\n", Batchhd.rel_name,
- lookucode(Batchhd.userid));
- close(Batch_fp);
- bmove(Batchhd.userid, Usercode, UCODE_SZ);
- if(ask("\tUpdate? "))
- update();
- }
- if (bequal(MODBATCH, fname, sizeof(MODBATCH) - 1))
- {
- Fileset = &fname[sizeof(MODBATCH) - 1];
- if ((Batch_fp = open(dp->d_name, O_RDONLY)) < 0)
- syserr("Can't open %s", dp->d_name);
- Batch_cnt = 0;
- if((i = getbatch(&descr, sizeof(descr))) != sizeof(descr))
- syserr(" cant read %d",i);
- printf("\tFound incomplete modify of %.12s, user = %s\n",
- descr.reldum.relid, lookucode(descr.reldum.relowner));
-
- bmove(descr.reldum.relowner, Usercode, sizeof(descr.reldum.relowner));
- close(Batch_fp);
- if (ask("\tComplete? "))
- modupdate();
- }
- }
- bmove(Utemp, Usercode, UCODE_SZ);
- ExitFn = tmpfn;
- closedir(dirp);
- }
- /*
- ** handles syserr's in the update processor
- */
- uperr()
- {
-
- if (Batch_fp)
- close(Batch_fp);
- Berror++;
- longjmp(Jmpbuffer,1);
- }
-
-
-
- /*
- ** Catch errors in other places
- */
- rubproc()
- {
- register int i;
- register struct desxx *p;
- extern struct desxx Desxx[];
- extern int Acc_init;
-
- Error++;
- printf("Unable to restore!\n");
-
- /* restore user code */
- bmove(Utemp, Usercode, sizeof Utemp);
-
- /* close all possible files */
- if (Acc_init)
- {
- closecatalog(TRUE);
- unldb();
- acc_close();
- }
-
- /* close users file */
- getuser(0);
-
- /* get everything else */
- for (i = Direc + 1; i <= NOFILE; i++)
- close(i);
- }
- /*
- ** looks up user by usercode in users file
- */
- char *
- lookucode(ucode)
- char ucode[2];
- {
- static char buf[MAXLINE + 1];
- register char *p;
-
- if (getuser(ucode, buf))
- syserr("cannot identify user %.2s", ucode);
- for (p = buf; *p != ':'; p++);
- *p = 0;
- return (buf);
- }
- /*
- ** CHECKATTS
- ** Checks that all attributes are in a relation
- */
- checkatts()
- {
- extern DESC Reldes, Attdes;
- register int i;
- register int once;
- TID tid, limtid, reltid;
- char key[MAXTUP];
- struct attribute atttup;
- struct relation reltup;
- char lastrel[MAXNAME + 2];
-
- once = 0;
- opencatalog("relation", OR_WRITE);
- opencatalog("attribute", OR_WRITE);
- clearkeys(&Attdes);
- lastrel[0] = '\0';
- if (find(&Attdes, NOKEY, &tid, &limtid))
- syserr("CHECKATT: find");
-
- while (!(i = get(&Attdes, &tid, &limtid, &atttup, TRUE)))
- {
- if (bequal(atttup.attrelid, lastrel, MAXNAME + 2))
- continue;
-
- clearkeys(&Reldes);
- setkey(&Reldes, key, atttup.attrelid, ATTRELID);
- setkey(&Reldes, key, atttup.attowner, ATTOWNER);
-
- if (i = getequal(&Reldes, key, &reltup, &reltid))
- {
- if (i < 0)
- syserr("ATTCHECK: getequal");
- if (!once++)
- printf("\tNo relation for attribute(s):\n");
- printf("\t");
- printup(&Attdes, &atttup);
- if (ask("\tDelete?"))
- if (i = delete(&Attdes, &tid))
- syserr("ATTCHECK: delete=%d", i);
- }
- else
- bmove(atttup.attrelid, lastrel, MAXNAME + 2);
- }
-
- if (i < 0)
- syserr("ATTCHECK: get=%d", i);
- }
- /*
- ** CHECKREL -- check relation relation against every thing else
- **
- ** Each tuple in the relation relation is read and each verifiable
- ** characteristic is checked for accuracy. Including the existence
- ** of the physical file (if not a view), the qrymod definition if
- ** appropriate and the secondary indexing.
- */
-
- checkrel()
- {
- extern DESC Reldes;
- register int i, j;
- struct relation rel;
- TID rtid, limtid;
- char fname[MAXNAME + 3];
-
- /* setup for search of entire relation */
- opencatalog("relation", OR_WRITE);
- clearkeys(&Reldes);
- if (find(&Reldes, NOKEY, &rtid, &limtid))
- syserr("CHECKREL: find");
-
- /* loop until all tuples checked */
- for (;;)
- {
- /* for each tuple in the rel-rel */
- i = get(&Reldes, &rtid, &limtid, &rel, TRUE);
- if (i > 0)
- break; /* have finished */
- if (i < 0)
- syserr("CHECKREL: get=%d", i);
-
- /* if not a view, check for the file */
- if ((rel.relstat & S_VIEW) != S_VIEW)
- {
- ingresname(rel.relid, rel.relowner, fname);
- if ((j = open(fname, O_RDWR)) == -1)
- {
- printf("\tNo file for:\n\t");
- printup(&Reldes, &rel);
- if (ask("\tDelete tuple? "))
- {
- if(j = delete(&Reldes, &rtid))
- syserr("CHECKREL: delete=%d", j);
- continue;
- }
- else
- /* don't call purge the file might still be there */
- Error++;
- }
- else
- close(j);
- }
-
- /* does it think that it has a secondary index */
- if (rel.relindxd > 0)
- {
- /* does it really have an index? */
- if (!hasndx(rel.relid, rel.relowner))
- {
- /* no, should it be fixed */
- printf("\tNo indexes entry for primary relation:\n\t");
- printup(&Reldes, &rel);
- if (ask("\tAdjust? "))
- {
- /* fix up relation relation entry */
- rel.relindxd = 0;
- if (i = replace(&Reldes, &rtid, &rel, FALSE))
- syserr("CHECKREL: replace=%d", i);
- }
- }
- }
-
- /* does it think that it is a secondary index */
- if (rel.relindxd == SECINDEX)
- {
- /* check to make sure */
- if (!isndx(rel.relid, rel.relowner))
- {
- /* none, what should be done? */
- printf("\tNo indexes entry for index:\n\t");
- printup(&Reldes, &rel);
- if(ask("\tDelete? "))
- {
- /*
- ** get rid of rel-rel tuple for
- ** secondary index,
- ** purge will do rest of
- ** removal if necessary
- */
- if (i = delete(&Reldes, &rtid))
- syserr("CHECKREL: delete=%d", i);
- continue; /* go on to next tuple */
- }
- }
- }
-
- /* if qrymod on in the database, check those catalogs too */
- if (Qrymod)
- {
- /*
- ** cannot deal with S_VBASE since there is no way to
- ** find the tree catalog entries without decoding the
- ** 'treetree' fields.
- **
- ** check to see if this is a view
- */
- if ((rel.relstat & S_VIEW) && !havetree(rel.relid, rel.relowner, mdVIEW))
- {
- /* no entry, should it be fixed? */
- printf("\tNo tree entry for this view:\n\t");
- printup(&Reldes, &rel);
- if (ask("\tDelete tuple? "))
- {
- /* delete relation entry */
- if (i = delete(&Reldes, &rtid))
- syserr("CHECKREL: delete=%d", i);
- continue; /* skip to next entry in rel-rel */
- }
- }
-
- /* check to see if has 'protect' entry */
- if ((rel.relstat & S_PROTUPS) && !isprot(rel.relid, rel.relowner, -1))
- {
- /* no entry, should the bit be reset */
- printf("\tNo protect entry for:\n\t");
- printup(&Reldes, &rel);
- if (ask("\tAdjust? "))
- {
- /* fix the bit */
- rel.relstat &= ~S_PROTUPS;
- if (i = replace(&Reldes, &rtid, &rel, FALSE))
- syserr("CHECKREL: replace=%d", i);
- }
- }
-
- /* check to see if has 'integrities entry */
- if ((rel.relstat & S_INTEG) && !isinteg(rel.relid, rel.relowner, -1))
- {
- /* no entry, should bit be reset */
- printf("\tNo integrities entry for:\n\t");
- printup(&Reldes, &rel);
- if (ask("\tAdjust? "))
- {
- /* fix up the bit */
- rel.relstat &= ~S_INTEG;
- if (i = replace(&Reldes, &rtid, &rel, FALSE))
- syserr("CHECKREL: replace=%d", i);
- }
- }
- }
- }
- }
- /*
- ** HASNDX -- the relation indicated an index, check it out
- **
- ** will search the index relation for all secondary indexes
- ** and check to see that each secondary index named has an
- ** entry in the relation relation.
- */
- hasndx(id, own)
- char id[MAXNAME];
- char own[2];
- {
- register int hasindexes;
- register int i, j;
- extern DESC Reldes, Inddes;
- TID rtid;
- struct relation rkey, rel;
- TID itid, ihitid;
- struct index ikey, ind;
-
- /* presume that answer is negative */
- hasindexes = FALSE;
-
- /* set search for all tuples with 'id' and 'own' in indexes */
- opencatalog("indexes", OR_WRITE);
- clearkeys(&Inddes);
- setkey(&Inddes, &ikey, id, IRELIDP);
- setkey(&Inddes, &ikey, own, IOWNERP);
- if (find(&Inddes, EXACTKEY, &itid, &ihitid, &ikey))
- syserr("HASNDX: find");
-
- /* for each possible tuple in the indexes relation */
- for (;;)
- {
- i = get(&Inddes, &itid, &ihitid, &ind, TRUE);
-
- /* check return values */
- if (i < 0)
- syserr("HASNDX: get=%d\n", i);
- if (i > 0)
- break; /* finished */
-
- /* if key doesn't match, skip to next tuple */
- if(kcompare(&Inddes, &ikey, &ind))
- continue;
- hasindexes = TRUE;
-
- /* verify that primary entry for sec index exists */
- opencatalog("relation", OR_WRITE);
- clearkeys(&Reldes);
- setkey(&Reldes, &rkey, ind.irelidi, RELID);
- setkey(&Reldes, &rkey, ind.iownerp, RELOWNER);
- if (j = getequal(&Reldes, &rkey, &rel, &rtid, FALSE))
- {
- /* one doesn't exist, should we ignore it */
- if (j < 0)
- syserr("HASNDX: getequal=%d", j);
- printf("\tNo secondary index for indexes entry:\n\t");
- printup(&Inddes, &ind);
- if (ask("\tDelete? "))
- {
- /* get rid of bad entry in indexes relation */
- if (j = delete(&Inddes, &itid))
- syserr("HASNDX: delete=%d", j);
- hasindexes = FALSE;
- }
- }
- }
- return (hasindexes);
- }
- /*
- ** ISNDX -- so you think that you're a secondary index, I'll check it out.
- **
- ** searches the indexes relation for the name of the primary relation
- ** and check to see if the primary is real. Will also update the
- ** 'relindxd' field of the primary if it isn't correct.
- */
- isndx(id, own)
- char id[MAXNAME];
- char own[2];
- {
- register int isindex;
- register int i;
- extern DESC Inddes;
- TID itid;
- struct index ind, ikey;
- extern DESC Reldes;
- TID rtid;
- struct relation rel, rkey;
-
- /* search for tuple in index relation, should only be one */
- opencatalog("indexes", OR_WRITE);
- clearkeys(&Inddes);
- setkey(&Inddes, &ikey, id, IRELIDI);
- setkey(&Inddes, &ikey, own, IOWNERP);
- if (i = getequal(&Inddes, &ikey, &ind, &itid))
- {
- /* there isn't a tuple in the indexes relation */
- if (i < 0)
- syserr("ISNDX: getequal=%d", i);
- isindex = FALSE;
- }
- else
- {
- isindex = TRUE;
-
- /* there is a tuple in the indexes relation */
- opencatalog("relation", OR_WRITE);
- clearkeys(&Reldes);
- setkey(&Reldes, &rkey, ind.irelidp, RELID);
- setkey(&Reldes, &rkey, ind.iownerp, RELOWNER);
-
- /* see if the primary relation exists */
- if (i = getequal(&Reldes, &rkey, &rel, &rtid))
- {
- /* no it doesn't */
- if (i < 0)
- syserr("ISNDX: getequal=%d", i);
-
- /* what should be done about it */
- printf("\tNo primary relation for index:\n\t");
- printup(&Inddes, &ind);
- if (ask("\tDelete?"))
- {
- /*
- ** get rid of indexes tuple,
- ** a FALSE return will also get rid
- ** of the relation tuple
- */
- if (i = delete(&Inddes, &itid))
- syserr("ISNDX: delete=%d", i);
- isindex = FALSE;
- }
- }
- else if (!(rel.relindxd > 0) || (rel.relstat & S_INDEX) == S_INDEX)
- {
- /*
- ** the primary tuple exists but isn't marked correctly
- */
- printf("\t%.12s is index for:\n\t", rel.relid);
- printup(&Reldes, &rel);
- if (ask("\tMark as indexed? "))
- {
- rel.relstat |= S_INDEX;
- rel.relindxd = SECBASE;
- if (i = replace(&Reldes, &rtid, &rel, FALSE))
- syserr("ISNDX: replace=%d", i);
- }
- }
- }
- return (isindex);
- }
- /*
- ** HAVETREE -- check tree catalog for an entry with right name and owner
- **
- ** The 'id' and 'own' parameters are used to look in the tree catalog
- ** for at least on tuple that also has a 'treetype' of 'mdvalue'.
- **
- ** If any tuples are found, havetree returns TRUE, else FALSE
- */
-
- havetree(id, own, mdvalue)
- char id[MAXNAME];
- char own[2];
- int mdvalue;
- {
- extern DESC Treedes;
- register int i;
- struct tree tkey, trent;
- TID ttid, thitid;
-
- /* search tree relation for tuple that matches */
- opencatalog("tree", OR_WRITE);
- clearkeys(&Treedes);
- setkey(&Treedes, &tkey, id, TREERELID);
- setkey(&Treedes, &tkey, own, TREEOWNER);
- setkey(&Treedes, &tkey, &mdvalue, TREETYPE);
-
- /* set search limit tids from the key */
- if (i = find(&Treedes, EXACTKEY, &ttid, &thitid, &tkey))
- syserr("HAVETREE: find=%d", i);
-
- for (;;)
- {
- i = get(&Treedes, &ttid, &thitid, &trent, TRUE);
-
- if (i < 0)
- syserr("HAVETREE: get=%d", i);
- if (i > 0)
- break; /* finished, didn't find one */
-
- if (kcompare(&Treedes, &tkey, &trent) == 0)
- return (TRUE);
- }
- return (FALSE);
- }
- /*
- ** ISPROT -- check in the 'protect' catalog for a tuple with right name, owner
- **
- ** search the 'protect' catalog for at least on tuple with matches the
- ** values in the parameters. If 'treeid' is >= 0 then it is not used as
- ** a key.
- **
- ** if one is found, returns TRUE, otherwise, returns FALSE
- */
-
- isprot(id, own, treeid)
- char id[MAXNAME];
- char own[2];
- int treeid;
- {
- extern DESC Prodes;
- register int i;
- struct protect pkey, pent;
- TID ptid, phitid;
-
- /* search the protect relation for at least on matching tuple */
- opencatalog("protect", OR_WRITE);
- clearkeys(&Prodes);
- setkey(&Prodes, &pkey, id, PRORELID);
- setkey(&Prodes, &pkey, own, PRORELOWN);
- if (treeid >= 0)
- setkey(&Prodes, &pkey, &treeid, PROTREE);
-
- /* set search limit tids from the keys */
- if (i = find(&Prodes, EXACTKEY, &ptid, &phitid, &pkey))
- syserr("ISPROT: find=%d", i);
-
- for (;;)
- {
- i = get(&Prodes, &ptid, &phitid, &pent, TRUE);
-
- if (i < 0)
- syserr("ISPROT: get=%d", i);
- if (i > 0)
- break; /* finished, didn't find one */
-
- if (kcompare(&Prodes, &pkey, &pent) == 0)
- return (TRUE);
- }
- return (FALSE);
- }
- /*
- ** ISINTEG -- check for a tuple in 'integrities'
- **
- ** searches the integrities relation for 'id' and 'own'.
- **
- ** returns TRUE if one is found, else FALSE
- */
-
- isinteg(id, own, treeid)
- char id[MAXNAME];
- char own[2];
- int treeid;
- {
- extern DESC Intdes;
- register int i;
- struct integrity inkey, integ;
- TID intid, inhitid;
-
- /* search the entire relation for a tuple that matches */
- opencatalog("integrities", OR_WRITE);
- clearkeys(&Intdes);
- setkey(&Intdes, &inkey, id, INTRELID);
- setkey(&Intdes, &inkey, own, INTRELOWNER);
- if (treeid >= 0)
- setkey(&Intdes, &inkey, &treeid, INTTREE);
-
- /* set the search limit tids from the key */
- if (i = find(&Intdes, EXACTKEY, &intid, &inhitid, &inkey))
- syserr("ISINTEG: find=%d", i);
-
- for (;;)
- {
- i = get(&Intdes, &intid, &inhitid, &integ, TRUE);
-
- if (i < 0)
- syserr("ISINTEG: get=%d", i);
- if (i > 0)
- break; /* finished, didn't find one */
-
- if (kcompare(&Intdes, &inkey, &integ) == 0)
- return (TRUE);
- }
- return (FALSE);
- }
- /*
- ** CHECKTREE -- check the tree catalog against the others
- */
-
- checktree()
- {
- extern DESC Treedes, Reldes;
- register int i;
- struct tree tkey, trent;
- TID ttid, thitid;
- struct relation rkey, rel;
- TID rtid;
-
- /* search the entire tree catalog */
- opencatalog("tree", OR_WRITE);
- clearkeys(&Treedes);
- if (i = find(&Treedes, NOKEY, &ttid, &thitid))
- syserr("CHECKTREE: find=%d", i);
-
- /* for each tuple in 'tree' */
- for (;;)
- {
- i = get(&Treedes, &ttid, &thitid, &trent, TRUE);
- if (i > 0)
- break; /* finished */
- if (i < 0)
- syserr("CHECKTREE: get=%d", i);
-
- /* verify that a tuple exists in the relation relation */
- opencatalog("relation", OR_WRITE);
- clearkeys(&Reldes);
- setkey(&Reldes, &rkey, trent.treerelid, RELID);
- setkey(&Reldes, &rkey, trent.treeowner, RELOWNER);
-
- /* fetch the tuple */
- if (i = getequal(&Reldes, &rkey, &rel, &rtid))
- {
- /*
- ** Oops, a tuple doesn't exist in the relation
- ** relation.
- **
- ** maybe it's just a fatal error
- */
- if (i < 0)
- syserr("CHECKTREE: getequal=%d", i);
-
- /* not a fatal error, what to do about it? */
- printf("\tNo relation tuple for:\n\t");
- printup(&Treedes, &trent);
- if (ask("\tDelete? "))
- {
- if (i = delete(&Treedes, &ttid))
- syserr("CHECKTREE: delete=%d", i);
- continue; /* go on to next tuple */
- }
- }
- else
- {
- /*
- ** Ah. A tuple does exist.
- **
- ** If the relstat bits are correct then we can stop
- ** here since elsewhere the 'protect' and 'integrity'
- ** entries were verified.
- */
- switch (trent.treetype)
- {
- case mdVIEW:
- /* mere existence is sufficient */
- break;
-
- case mdPROT:
- if ((rel.relstat & S_PROTUPS) != S_PROTUPS)
- {
- printf("\tNo 'protect' entry for:\n\t");
- deltup:
- printup(&Treedes, &trent);
- if (ask("\tDelete? "))
- {
- if (i = delete(&Treedes, &ttid))
- syserr("CHECKTREE: delete=%d", i);
- continue;
- }
- }
- break;
-
- case mdINTEG:
- if ((rel.relstat & S_INTEG) != S_INTEG)
- {
- printf("\tNo 'integrities' entry for:\n\t");
- goto deltup;
- }
- break;
-
- default:
- syserr("Unknown treetype: %d\n", trent.treetype);
- }
- }
- }
- }
- /*
- ** CHECKPROTECT
- */
-
- checkprotect()
- {
- register int i;
- extern DESC Reldes, Prodes;
- struct protect pkey, pent;
- TID ptid, phitid;
- struct relation rkey, rel;
- TID rtid;
-
- /* for each entry in the 'protect' relation */
- opencatalog("protect", OR_WRITE);
- clearkeys(&Prodes);
- if (i = find(&Prodes, NOKEY, &ptid, &phitid))
- syserr("CHECKPROTECT: find=%d", i);
-
- for (;;)
- {
- i = get(&Prodes, &ptid, &phitid, &pent, TRUE);
- if (i > 0)
- break; /* finished */
- if (i < 0)
- syserr("CHECKPROTECT: get=%d", i);
-
- /* verify that a tuple exists in 'relation' */
- opencatalog("relation", OR_WRITE);
- clearkeys(&Reldes);
- setkey(&Reldes, &rkey, pent.prorelid, RELID);
- setkey(&Reldes, &rkey, pent.prorelown, RELOWNER);
-
- /* fetch the tuple if possible */
- if (i = getequal(&Reldes, &rkey, &rel, &rtid))
- {
- /*
- ** Oops. A tuple doesn't exits in 'relation'
- **
- ** Maybe it's just a fatal error.
- */
- if (i < 0)
- syserr("CHECKPROTECT: getequal=%d", i);
-
- /* not a fatal error, what to do? */
- printf("\tNo relation for 'protect' entry:\n\t");
- printup(&Prodes, &pent);
- if (ask("\tRemove 'protect' entry? "))
- {
- if (i = delete(&Prodes, &ptid))
- syserr("CHECKPROTECT: delete=%d", i);
- continue; /* go on to next tuple */
- }
- }
- else
- {
- /* 'relation' entry exists, check for the tree entry */
- if (pent.protree >= 0)
- {
- if (!havetree(pent.prorelid, pent.prorelown, mdPROT))
- {
- /* no tuples in 'tree' */
- printf("\tNo tree for:\n\t");
- printup(&Prodes, &pent);
- if (ask("\tDelete entry and fix relation status bits? "))
- {
- if (i = delete(&Prodes, &pent))
- syserr("CHECKPROTECT: delete=%d", i);
- rel.relstat &= ~S_PROTUPS;
- if (i = replace(&Reldes, &rtid, &rel, FALSE))
- syserr("CHECKPROTECT: replace=%d", i);
- continue; /* go on to next tuple */
- }
- }
- }
- if ((rel.relstat & S_PROTUPS) != S_PROTUPS)
- {
- /* bits not set correctly */
- printf("\tIncorrect relation status bits for:\n\t");
- printup(&Reldes, &rel);
- if (ask("\tAdjust? "))
- {
- rel.relstat |= S_PROTUPS;
- if (i = replace(&Reldes, &rtid, &rel, FALSE))
- syserr("CHECKPROTECT: replace=%d", i);
- continue; /* go on to next tuple */
- }
- }
- }
- }
- }
- /*
- ** CHECKINTEG
- */
-
- checkinteg()
- {
- register int i;
- extern DESC Reldes, Intdes;
- struct integrity inkey, inent;
- TID intid, inhitid;
- struct relation rkey, rel;
- TID rtid;
-
- /* for each entry in 'integrities' */
- opencatalog("integrities", OR_WRITE);
- clearkeys(&Intdes);
- if (i = find(&Intdes, NOKEY, &intid, &inhitid))
- syserr("CHECKINTEG: find=%d", i);
-
- for (;;)
- {
- i = get(&Intdes, &intid, &inhitid, &inent, TRUE);
- if (i > 0)
- break; /* finished */
- if (i < 0)
- syserr("CHECKINTEG: get=%d", i);
-
- /* verify that a tuple exists in 'relation' */
- opencatalog("relation", OR_WRITE);
- clearkeys(&Reldes);
- setkey(&Reldes, &rkey, inent.intrelid, RELID);
- setkey(&Reldes, &rkey, inent.intrelowner, RELOWNER);
-
- /* fetch the tuple if possible */
- if (i = getequal(&Reldes, &rkey, &rel, &rtid))
- {
- /*
- ** Oops. A tuple doesn't exits in 'relation'
- **
- ** Maybe it's just a fatal error.
- */
- if (i < 0)
- syserr("CHECKINTEG: getequal=%d", i);
-
- /* not a fatal error, what to do? */
- printf("\tNo relation for 'integrities' entry:\n\t");
- printup(&Intdes, &inent);
- if (ask("\tRemove 'integrities' entry? "))
- {
- if (i = delete(&Intdes, &intid))
- syserr("CHECKINTEG: delete=%d", i);
- continue; /* go on to next tuple */
- }
- }
- else
- {
- /* 'relation' entry exists, check for the tree entry */
- if (inent.inttree >= 0)
- {
- if (!havetree(inent.intrelid, inent.intrelowner, mdINTEG))
- {
- /* no tuples in 'tree' */
- printf("\tNo tree for:\n\t");
- printup(&Intdes, &inent);
- if (ask("\tDelete entry and fix relation status bits? "))
- {
- if (i = delete(&Intdes, &inent))
- syserr("CHECKINTEG: delete=%d", i);
- rel.relstat &= ~S_INTEG;
- if (i = replace(&Reldes, &rtid, &rel, FALSE))
- syserr("CHECKINTEG: replace=%d", i);
- continue; /* go on to next tuple */
- }
- }
- }
- if ((rel.relstat & S_INTEG) != S_INTEG)
- {
- /* bits not set correctly */
- printf("\tIncorrect relation status bits for:\n\t");
- printup(&Reldes, &rel);
- if (ask("\tAdjust? "))
- {
- rel.relstat |= S_INTEG;
- if (i = replace(&Reldes, &rtid, &rel, FALSE))
- syserr("CHECKINTEG: replace=%d", i);
- continue; /* go on to next tuple */
- }
- }
- }
- }
- }
-